package com.tbynet.jwp.framework.kit;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 集合处理工具类
 *
 * @author 佰亿互联
 * @version 3.1
 * @since 2025-11-04
 */
public class CollectionKit {

    // ========== 集合创建方法 ==========

    /**
     * 安全地创建不可变列表（Java 8 兼容）
     *
     * @param elements 列表元素
     * @param <T> 元素类型
     * @return 不可变列表
     *
     * @example
     * <pre>{@code
     * List<String> list = CollectionKit.safeListOf("a", "b", "c");
     * // 返回不可变的包含 ["a", "b", "c"] 的列表
     * }</pre>
     */
    @SafeVarargs
    public static <T> List<T> safeListOf(T... elements) {
        if (elements == null || elements.length == 0) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableList(Arrays.asList(elements));
    }

    /**
     * 安全地创建列表副本（Java 8 兼容）
     *
     * @param original 原始列表
     * @param <T> 元素类型
     * @return 列表副本
     *
     * @example
     * <pre>{@code
     * List<String> original = Arrays.asList("a", "b", "c");
     * List<String> copy = CollectionKit.safeListCopy(original);
     * // 返回原始列表的不可变副本
     * }</pre>
     */
    public static <T> List<T> safeListCopy(List<T> original) {
        if (original == null || original.isEmpty()) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableList(new ArrayList<>(original));
    }

    /**
     * 安全地创建映射副本（Java 8 兼容）
     *
     * @param original 原始映射
     * @param <K> 键类型
     * @param <V> 值类型
     * @return 映射副本
     *
     * @example
     * <pre>{@code
     * Map<String, Integer> original = new HashMap<>();
     * original.put("a", 1);
     * Map<String, Integer> copy = CollectionKit.safeMapCopy(original);
     * // 返回原始映射的不可变副本
     * }</pre>
     */
    public static <K, V> Map<K, V> safeMapCopy(Map<K, V> original) {
        if (original == null || original.isEmpty()) {
            return Collections.emptyMap();
        }
        return Collections.unmodifiableMap(new HashMap<>(original));
    }

    /**
     * 安全地创建集合副本
     *
     * @param original 原始集合
     * @param <T> 元素类型
     * @return 集合副本
     *
     * @example
     * <pre>{@code
     * Set<String> original = new HashSet<>(Arrays.asList("a", "b", "c"));
     * Set<String> copy = CollectionKit.safeSetCopy(original);
     * // 返回原始集合的不可变副本
     * }</pre>
     */
    public static <T> Set<T> safeSetCopy(Set<T> original) {
        if (original == null || original.isEmpty()) {
            return Collections.emptySet();
        }
        return Collections.unmodifiableSet(new HashSet<>(original));
    }

    // ========== 集合验证方法 ==========

    /**
     * 检查集合是否为空
     *
     * @param collection 集合
     * @return 如果集合为null或空返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * boolean isEmpty = CollectionKit.isEmpty(Arrays.asList("a", "b"));
     * // 返回 false
     * }</pre>
     */
    public static boolean isEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 检查集合是否不为空
     *
     * @param collection 集合
     * @return 如果集合不为null且不为空返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * boolean isNotEmpty = CollectionKit.isNotEmpty(Arrays.asList("a", "b"));
     * // 返回 true
     * }</pre>
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 检查Map是否为空
     *
     * @param map Map
     * @return 如果Map为null或空返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * Map<String, String> map = new HashMap<>();
     * boolean isEmpty = CollectionKit.isEmpty(map);
     * // 返回 true
     * }</pre>
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }

    /**
     * 检查Map是否不为空
     *
     * @param map Map
     * @return 如果Map不为null且不为空返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * Map<String, String> map = new HashMap<>();
     * map.put("key", "value");
     * boolean isNotEmpty = CollectionKit.isNotEmpty(map);
     * // 返回 true
     * }</pre>
     */
    public static boolean isNotEmpty(Map<?, ?> map) {
        return !isEmpty(map);
    }

    /**
     * 检查数组是否为空
     *
     * @param array 数组
     * @return 如果数组为null或空返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * boolean isEmpty = CollectionKit.isEmpty(new String[]{"a", "b"});
     * // 返回 false
     * }</pre>
     */
    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 检查数组是否不为空
     *
     * @param array 数组
     * @return 如果数组不为null且不为空返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * boolean isNotEmpty = CollectionKit.isNotEmpty(new String[]{"a", "b"});
     * // 返回 true
     * }</pre>
     */
    public static boolean isNotEmpty(Object[] array) {
        return !isEmpty(array);
    }

    // ========== 集合转换方法 ==========

    /**
     * 将集合转换为字符串（用指定分隔符连接）
     *
     * @param collection 集合
     * @param delimiter 分隔符
     * @return 连接后的字符串
     *
     * @example
     * <pre>{@code
     * List<String> list = Arrays.asList("a", "b", "c");
     * String result = CollectionKit.join(list, ",");
     * // 返回 "a,b,c"
     * }</pre>
     */
    public static String join(Collection<?> collection, String delimiter) {
        if (isEmpty(collection)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        Iterator<?> iterator = collection.iterator();
        while (iterator.hasNext()) {
            sb.append(iterator.next());
            if (iterator.hasNext()) {
                sb.append(delimiter);
            }
        }
        return sb.toString();
    }

    /**
     * 将集合转换为字符串（用逗号连接）
     *
     * @param collection 集合
     * @return 连接后的字符串
     *
     * @example
     * <pre>{@code
     * List<String> list = Arrays.asList("a", "b", "c");
     * String result = CollectionKit.join(list);
     * // 返回 "a,b,c"
     * }</pre>
     */
    public static String join(Collection<?> collection) {
        return join(collection, ",");
    }

    /**
     * 提取集合中元素的某个属性组成新列表
     *
     * @param collection 原始集合
     * @param mapper 属性提取函数
     * @param <T> 原始元素类型
     * @param <R> 结果元素类型
     * @return 属性列表
     *
     * @example
     * <pre>{@code
     * List<User> users = Arrays.asList(
     *     new User(1, "Alice"),
     *     new User(2, "Bob")
     * );
     * List<String> names = CollectionKit.extractField(users, User::getName);
     * // 返回 ["Alice", "Bob"]
     * }</pre>
     */
    public static <T, R> List<R> extractField(Collection<T> collection, Function<T, R> mapper) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }

        List<R> result = new ArrayList<>(collection.size());
        for (T item : collection) {
            R field = mapper.apply(item);
            if (field != null) {
                result.add(field);
            }
        }
        return result;
    }

    /**
     * 将列表转换为Map
     *
     * @param list 列表
     * @param keyMapper 键提取函数
     * @param <K> 键类型
     * @param <V> 值类型
     * @return Map
     *
     * @example
     * <pre>{@code
     * List<User> users = Arrays.asList(
     *     new User(1, "Alice"),
     *     new User(2, "Bob")
     * );
     * Map<Integer, User> userMap = CollectionKit.toMap(users, User::getId);
     * // 返回 {1=User(1,"Alice"), 2=User(2,"Bob")}
     * }</pre>
     */
    public static <K, V> Map<K, V> toMap(Collection<V> list, Function<V, K> keyMapper) {
        if (isEmpty(list)) {
            return Collections.emptyMap();
        }

        Map<K, V> map = new HashMap<>(list.size());
        for (V item : list) {
            K key = keyMapper.apply(item);
            if (key != null) {
                map.put(key, item);
            }
        }
        return map;
    }

    /**
     * 将列表转换为Map（支持值转换）
     *
     * @param list 列表
     * @param keyMapper 键提取函数
     * @param valueMapper 值提取函数
     * @param <K> 键类型
     * @param <V> 值类型
     * @param <T> 原始元素类型
     * @return Map
     *
     * @example
     * <pre>{@code
     * List<User> users = Arrays.asList(
     *     new User(1, "Alice"),
     *     new User(2, "Bob")
     * );
     * Map<Integer, String> userMap = CollectionKit.toMap(
     *     users, User::getId, User::getName
     * );
     * // 返回 {1="Alice", 2="Bob"}
     * }</pre>
     */
    public static <T, K, V> Map<K, V> toMap(Collection<T> list,
                                            Function<T, K> keyMapper,
                                            Function<T, V> valueMapper) {
        if (isEmpty(list)) {
            return Collections.emptyMap();
        }

        Map<K, V> map = new HashMap<>(list.size());
        for (T item : list) {
            K key = keyMapper.apply(item);
            V value = valueMapper.apply(item);
            if (key != null && value != null) {
                map.put(key, value);
            }
        }
        return map;
    }

    // ========== 集合过滤方法 ==========

    /**
     * 过滤集合
     *
     * @param collection 原始集合
     * @param predicate 过滤条件
     * @param <T> 元素类型
     * @return 过滤后的列表
     *
     * @example
     * <pre>{@code
     * List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
     * List<Integer> evenNumbers = CollectionKit.filter(numbers, n -> n % 2 == 0);
     * // 返回 [2, 4]
     * }</pre>
     */
    public static <T> List<T> filter(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }

        List<T> result = new ArrayList<>();
        for (T item : collection) {
            if (predicate.test(item)) {
                result.add(item);
            }
        }
        return result;
    }

    /**
     * 过滤集合中的非空元素
     *
     * @param collection 原始集合
     * @param <T> 元素类型
     * @return 非空元素列表
     *
     * @example
     * <pre>{@code
     * List<String> list = Arrays.asList("a", null, "b", null, "c");
     * List<String> nonNullList = CollectionKit.filterNonNull(list);
     * // 返回 ["a", "b", "c"]
     * }</pre>
     */
    public static <T> List<T> filterNonNull(Collection<T> collection) {
        return filter(collection, Objects::nonNull);
    }

    /**
     * 分页获取集合子集
     *
     * @param collection 原始集合
     * @param pageNumber 页码（从1开始）
     * @param pageSize 每页大小
     * @param <T> 元素类型
     * @return 分页后的列表
     *
     * @example
     * <pre>{@code
     * List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
     * List<Integer> page = CollectionKit.paginate(numbers, 2, 3);
     * // 返回 [4, 5, 6]（第二页，每页3条）
     * }</pre>
     */
    public static <T> List<T> paginate(Collection<T> collection, int pageNumber, int pageSize) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }

        if (pageNumber < 1) {
            pageNumber = 1;
        }
        if (pageSize < 1) {
            pageSize = 10;
        }

        int startIndex = (pageNumber - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, collection.size());

        if (startIndex >= collection.size()) {
            return Collections.emptyList();
        }

        List<T> list = collection instanceof List ?
                (List<T>) collection : new ArrayList<>(collection);

        return list.subList(startIndex, endIndex);
    }

    // ========== 集合操作方法 ==========

    /**
     * 获取集合的第一个元素
     *
     * @param collection 集合
     * @param <T> 元素类型
     * @return 第一个元素，如果集合为空返回null
     *
     * @example
     * <pre>{@code
     * List<String> list = Arrays.asList("a", "b", "c");
     * String first = CollectionKit.first(list);
     * // 返回 "a"
     * }</pre>
     */
    public static <T> T first(Collection<T> collection) {
        if (isEmpty(collection)) {
            return null;
        }

        if (collection instanceof List) {
            return ((List<T>) collection).get(0);
        }

        return collection.iterator().next();
    }

    /**
     * 获取集合的最后一个元素
     *
     * @param collection 集合
     * @param <T> 元素类型
     * @return 最后一个元素，如果集合为空返回null
     *
     * @example
     * <pre>{@code
     * List<String> list = Arrays.asList("a", "b", "c");
     * String last = CollectionKit.last(list);
     * // 返回 "c"
     * }</pre>
     */
    public static <T> T last(Collection<T> collection) {
        if (isEmpty(collection)) {
            return null;
        }

        if (collection instanceof List) {
            List<T> list = (List<T>) collection;
            return list.get(list.size() - 1);
        }

        T last = null;
        for (T item : collection) {
            last = item;
        }
        return last;
    }

    /**
     * 合并多个集合
     *
     * @param collections 多个集合
     * @param <T> 元素类型
     * @return 合并后的列表
     *
     * @example
     * <pre>{@code
     * List<String> list1 = Arrays.asList("a", "b");
     * List<String> list2 = Arrays.asList("c", "d");
     * List<String> merged = CollectionKit.merge(list1, list2);
     * // 返回 ["a", "b", "c", "d"]
     * }</pre>
     */
    @SafeVarargs
    public static <T> List<T> merge(Collection<T>... collections) {
        if (collections == null || collections.length == 0) {
            return Collections.emptyList();
        }

        List<T> result = new ArrayList<>();
        for (Collection<T> collection : collections) {
            if (isNotEmpty(collection)) {
                result.addAll(collection);
            }
        }
        return result;
    }

    /**
     * 对集合进行分组
     *
     * @param collection 集合
     * @param classifier 分组函数
     * @param <T> 元素类型
     * @param <K> 分组键类型
     * @return 分组后的Map
     *
     * @example
     * <pre>{@code
     * List<User> users = Arrays.asList(
     *     new User(1, "Alice", "IT"),
     *     new User(2, "Bob", "HR"),
     *     new User(3, "Charlie", "IT")
     * );
     * Map<String, List<User>> grouped = CollectionKit.groupBy(users, User::getDepartment);
     * // 返回 {"IT": [User1, User3], "HR": [User2]}
     * }</pre>
     */
    public static <T, K> Map<K, List<T>> groupBy(Collection<T> collection,
                                                 Function<T, K> classifier) {
        if (isEmpty(collection)) {
            return Collections.emptyMap();
        }

        Map<K, List<T>> result = new HashMap<>();
        for (T item : collection) {
            K key = classifier.apply(item);
            if (key != null) {
                result.computeIfAbsent(key, k -> new ArrayList<>()).add(item);
            }
        }
        return result;
    }

    /**
     * 对集合进行排序
     *
     * @param collection 集合
     * @param comparator 比较器
     * @param <T> 元素类型
     * @return 排序后的列表
     *
     * @example
     * <pre>{@code
     * List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5);
     * List<Integer> sorted = CollectionKit.sort(numbers, Integer::compareTo);
     * // 返回 [1, 1, 3, 4, 5]
     * }</pre>
     */
    public static <T> List<T> sort(Collection<T> collection, Comparator<T> comparator) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }

        List<T> list = new ArrayList<>(collection);
        list.sort(comparator);
        return list;
    }

    /**
     * 对集合进行自然排序
     *
     * @param collection 集合
     * @param <T> 元素类型（必须实现Comparable接口）
     * @return 排序后的列表
     *
     * @example
     * <pre>{@code
     * List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5);
     * List<Integer> sorted = CollectionKit.sort(numbers);
     * // 返回 [1, 1, 3, 4, 5]
     * }</pre>
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> List<T> sort(Collection<T> collection) {
        return sort(collection, (Comparator<T>) Comparator.naturalOrder());
    }

    // ========== 集合统计方法 ==========

    /**
     * 计算集合中满足条件的元素数量
     *
     * @param collection 集合
     * @param predicate 条件
     * @param <T> 元素类型
     * @return 满足条件的元素数量
     *
     * @example
     * <pre>{@code
     * List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
     * long count = CollectionKit.count(numbers, n -> n % 2 == 0);
     * // 返回 2
     * }</pre>
     */
    public static <T> long count(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return 0;
        }

        long count = 0;
        for (T item : collection) {
            if (predicate.test(item)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 判断集合中是否存在满足条件的元素
     *
     * @param collection 集合
     * @param predicate 条件
     * @param <T> 元素类型
     * @return 如果存在满足条件的元素返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
     * boolean exists = CollectionKit.exists(numbers, n -> n > 3);
     * // 返回 true
     * }</pre>
     */
    public static <T> boolean exists(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return false;
        }

        for (T item : collection) {
            if (predicate.test(item)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断集合中是否所有元素都满足条件
     *
     * @param collection 集合
     * @param predicate 条件
     * @param <T> 元素类型
     * @return 如果所有元素都满足条件返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * List<Integer> numbers = Arrays.asList(2, 4, 6, 8);
     * boolean allEven = CollectionKit.forAll(numbers, n -> n % 2 == 0);
     * // 返回 true
     * }</pre>
     */
    public static <T> boolean forAll(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return true; // 空集合认为所有元素都满足条件
        }

        for (T item : collection) {
            if (!predicate.test(item)) {
                return false;
            }
        }
        return true;
    }

    // ========== Map操作方法 ==========

    /**
     * 从Map中安全获取值，如果键不存在返回默认值
     *
     * @param map Map
     * @param key 键
     * @param defaultValue 默认值
     * @param <K> 键类型
     * @param <V> 值类型
     * @return 值或默认值
     *
     * @example
     * <pre>{@code
     * Map<String, Integer> map = new HashMap<>();
     * map.put("a", 1);
     * Integer value = CollectionKit.getOrDefault(map, "b", 0);
     * // 返回 0
     * }</pre>
     */
    public static <K, V> V getOrDefault(Map<K, V> map, K key, V defaultValue) {
        if (map == null) {
            return defaultValue;
        }
        V value = map.get(key);
        return value != null ? value : defaultValue;
    }

    /**
     * 从Map中安全获取值，如果键不存在返回null
     *
     * @param map Map
     * @param key 键
     * @param <K> 键类型
     * @param <V> 值类型
     * @return 值或null
     *
     * @example
     * <pre>{@code
     * Map<String, Integer> map = new HashMap<>();
     * map.put("a", 1);
     * Integer value = CollectionKit.getOrNull(map, "b");
     * // 返回 null
     * }</pre>
     */
    public static <K, V> V getOrNull(Map<K, V> map, K key) {
        return getOrDefault(map, key, null);
    }

    /**
     * 获取Map的所有键
     *
     * @param map Map
     * @param <K> 键类型
     * @param <V> 值类型
     * @return 键的列表
     *
     * @example
     * <pre>{@code
     * Map<String, Integer> map = new HashMap<>();
     * map.put("a", 1);
     * map.put("b", 2);
     * List<String> keys = CollectionKit.keys(map);
     * // 返回 ["a", "b"]
     * }</pre>
     */
    public static <K, V> List<K> keys(Map<K, V> map) {
        if (isEmpty(map)) {
            return Collections.emptyList();
        }
        return new ArrayList<>(map.keySet());
    }

    /**
     * 获取Map的所有值
     *
     * @param map Map
     * @param <K> 键类型
     * @param <V> 值类型
     * @return 值的列表
     *
     * @example
     * <pre>{@code
     * Map<String, Integer> map = new HashMap<>();
     * map.put("a", 1);
     * map.put("b", 2);
     * List<Integer> values = CollectionKit.values(map);
     * // 返回 [1, 2]
     * }</pre>
     */
    public static <K, V> List<V> values(Map<K, V> map) {
        if (isEmpty(map)) {
            return Collections.emptyList();
        }
        return new ArrayList<>(map.values());
    }

    /**
     * 过滤Map
     *
     * @param map 原始Map
     * @param predicate 过滤条件
     * @param <K> 键类型
     * @param <V> 值类型
     * @return 过滤后的Map
     *
     * @example
     * <pre>{@code
     * Map<String, Integer> map = new HashMap<>();
     * map.put("a", 1);
     * map.put("b", 2);
     * map.put("c", 3);
     * Map<String, Integer> filtered = CollectionKit.filterMap(
     *     map, (k, v) -> v > 1
     * );
     * // 返回 {"b": 2, "c": 3}
     * }</pre>
     */
    public static <K, V> Map<K, V> filterMap(Map<K, V> map,
                                             java.util.function.BiPredicate<K, V> predicate) {
        if (isEmpty(map)) {
            return Collections.emptyMap();
        }

        Map<K, V> result = new HashMap<>();
        for (Map.Entry<K, V> entry : map.entrySet()) {
            if (predicate.test(entry.getKey(), entry.getValue())) {
                result.put(entry.getKey(), entry.getValue());
            }
        }
        return result;
    }
}